﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Mail;
using Pyco.Framework;
using System.Net;
using System.Threading;

namespace AutoSendMail
{
    
    class MailProvider
    {
        #region Variable Declarations
        private List<SMTPConfig> smtpList = null;
        private MailList mailList = null;
        private String subject = null;
        private String body = null;
        private Encoding bodyEncoding = Encoding.UTF8;
        private Boolean? isBodyHtml = true;
        private MailPriority priority = MailPriority.High;
        private SMTPConfig activeConfig = null;
//        private System.Int32? activeSMTPIndex = null;
        private SmtpClient smtpClient = null;
        private String senderEmail = null;
        private String senderName = null;
        private String toMail = null;
        private Boolean? checkEmailAddress = null;
        #endregion Variable Declarations

        public delegate void SentMailHandler(object sender);

        public event SentMailHandler MailSent_Completed ;
        public event SentMailHandler MailSentAll_Completed;

        public int NumberOfEmailHasBeenAccessed = 0;


        public MailProvider()
        {
            smtpList = new List<SMTPConfig>();
            mailList = new MailList();
        }

        #region properties
        public MailList SmtpList
        {
            get { return mailList; }
            set { mailList = value; }
        }
        public String SenderEmail
        {
            get { return senderEmail; }
            set { senderEmail = value; }
        }
        public Boolean? CheckEmailAddress
        {
            get { return checkEmailAddress; }
            set { checkEmailAddress = value; }
        }
        public String SenderName
        {
            get { return senderName; }
            set { senderName = value; }
        }

        public MailPriority Priority
        {
            get { return priority; }
            set { priority = value; }
        }

        public Boolean? IsBodyHtml
        {
            get { return isBodyHtml; }
            set { isBodyHtml = value; }
        }

        public Encoding BodyEncoding
        {
            get { return bodyEncoding; }
            set { bodyEncoding = value; }
        }

        public String Body
        {
            get { return body; }
            set { body = value; }
        }

        public String Subject
        {
            get { return subject; }
            set { subject = value; }
        }
        
        #endregion properties

        #region Public Methods
        public void addToSmtpList(SMTPConfig smtpConfig)
        {
            smtpList.Add(smtpConfig);
        }

        public bool sendAll()
        {
            try
            {
                for (int i = 0; i < mailList.Count(); i++)
                {
                    this.toMail = mailList[i];
                    SendEmail();
                    Thread.Sleep(AppConfig.SleepInterval);
                }
                return true;
            }

            finally
            {
                if (MailSentAll_Completed != null)
                {
                    MailSentAll_Completed(this);
                }
            }
        }
        #endregion Public Methods

        #region Private Methods
        private void updateSMTPList(SMTPConfig smtp)
        {
        //    Logger.Info("Begin update SMTP List !");
            for (int i = 0; i < smtpList.Count; i++)
            {
                if (smtpList[i].Host == smtp.Host && smtpList[i].Port == smtp.Port
                    && smtpList[i].UserName == smtp.UserName && smtpList[i].PassWord == smtp.PassWord
                    )
                {
                    smtpList[i].CurrentUse++;
                    if (smtpList[i].CurrentUse >= smtpList[i].MaxUse)
                    {
                        Logger.Info("SMTP exceeding the max use. SMTP info: " + smtpList[i].UserName);
                        smtpList.RemoveAt(i);
                    }
                        
                 //   Logger.Info("Finish update SMTP List");
                }
            }
        }
        private SMTPConfig getRandomSMTP()
        {
            Logger.Info("Begin Getting Random SMTP... !");
            if (smtpList.Count <= 0) return null;
            Random rd = new Random();
            do
            {
                int index = rd.Next(0, smtpList.Count);
                if (smtpList[index].CurrentUse < smtpList[index].MaxUse)
                {
                    Logger.Info(String.Format( "SMTP info: {0},{1},{2},{3}, current use: {4}" , smtpList[index].Host,
                        smtpList[index].Port, smtpList[index].UserName, smtpList[index].PassWord, smtpList[index].CurrentUse));
                    Logger.Info("Finish Getting Random SMTP");
                    return smtpList[index];
                }
            } while (true);   
        }
        private bool SendEmail()
        {
            try
            {
                Logger.Info("---------------------");
                Logger.Info("Begin Sending email... !");
                Logger.Info(String.Format("Email Info: Address: {0}!", this.toMail));

                if ((bool)CheckEmailAddress)
                {
                    EmailChecker emailChecker = new EmailChecker();
                    String resultText = "";
                    if (!emailChecker.isValidEmailAddress(this.toMail, ref resultText))
                    {
                        Logger.Info("Finish Sending email. Can NOT Send Email. " + resultText);
                        Logger.Info("-------------------");
                        return false;
                    }
                }

                this.activeConfig = getRandomSMTP();
                
                //create the mail message
                MailMessage mail = new MailMessage();

                //set the addresses
                mail.From = new MailAddress(this.senderEmail, "LÊ ĐỨC SƠN", Encoding.UTF8);
                mail.To.Add(this.toMail);

                //set the content
                mail.Subject = this.Subject;
                mail.Body = this.Body;
                mail.IsBodyHtml = true;
                mail.BodyEncoding = Encoding.UTF8;
                //add an attachment from the filesystem
                //mail.Attachments.Add(new Attachment(filePath));
                mail.Priority = MailPriority.High;
                //send the message

                smtpClient = new SmtpClient(this.activeConfig.Host, Convert.ToInt32(activeConfig.Port));
                smtpClient.EnableSsl = true;
                if (this.activeConfig.UserName != "")
                {
                    smtpClient.Credentials = new NetworkCredential(this.activeConfig.UserName, this.activeConfig.PassWord);
                }
                smtpClient.Send(mail);

                mail.Dispose();
                updateSMTPList(this.activeConfig);
                Logger.Info("Finish Sending email. EMail has been sent successful !");
                Logger.Info("-------------------");
                return true;
            }
            catch (Exception ex)
            {
                // sendToAdmin
                // sendToClient
                Logger.Error(ex.Message);
                return false;
            }
            finally
            {
                NumberOfEmailHasBeenAccessed++;
                if (MailSent_Completed != null)
                {
                    MailSent_Completed(this);
                }
            }
        }
        #endregion Private Methods
    }
}
